#include <iostream>
#include <pthread.h>
#include <unistd.h>
#include <ctime>
#include "ring_queue.hpp"

using namespace std;

struct task;

struct thread_node {
    ring_queue<task> *rq;
    string thread_name;
};

struct task {
    task(int x = 0, int y = 0) : _x(x), _y(y) {}

    int run() {
        return _x + _y;
    }

    int _x;
    int _y;
};

void *producer(void *args) {
    thread_node *tn = static_cast<thread_node *>(args);
    ring_queue<task> *rq = tn->rq;
    while(true) {
        // 1. 获取数据
        int x = rand() % 10 + 1, y = rand() % 10 + 1;

        // 2. 生产数据
        rq->push({x, y});
        cout << tn->thread_name << " Produce a date, it is : " << x << " " << y << endl;
        sleep(1);
    }
    delete tn;
    return nullptr;
}

void *consumer(void *args) {
    thread_node *tn = static_cast<thread_node *>(args);
    ring_queue<task> *rq = tn->rq;
    while(true) {
        // 1. 消费数据
        task data;
        rq->pop(&data);

        // 2. 处理数据
        cout << tn->thread_name << " consume a date, it is : " << data.run() << endl;
    }
    delete tn;
    return nullptr;
}

int main() {
    srand(time(nullptr));

    pthread_t c[3], p[5];
    ring_queue<task> *rq = new ring_queue<task>;
    for(int i = 0; i < 3; ++i) {
        thread_node *tn = new thread_node;
        tn->rq = rq;
        tn->thread_name = "consumer_" + to_string(i);
        pthread_create(c + i, nullptr, consumer, tn);
    }
    for(int i = 0; i < 5; ++i) {
        thread_node *tn = new thread_node;
        tn->rq = rq;
        tn->thread_name = "producer_" + to_string(i);
        pthread_create(p + i, nullptr, producer, tn);
    }

    delete rq;
    for(int i = 0; i < 3; ++i) {
        pthread_join(c[i], nullptr);
    }

    for(int i = 0; i < 5; ++i) {
        pthread_join(p[i], nullptr);
    }
    return 0;
}